package com.common.context;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 保存所有的 controller 和 controller 对应的方法
public class RequestContext {

    private Map<String,Bean> beans = new HashMap<>();

    private static RequestContext requestContext = new RequestContext();

    private RequestContext(){}

    public static RequestContext getRequestContext(){
        return requestContext;
    }

    public void loadContext(Class clazz) {
        // 1. 获取父路径
        String parent = getParentLocation(clazz);
        // 2. 遍历 子包
        List<File> fileList = new ArrayList<>();
        listFiles(parent, fileList);
        // 3. 拼接全路径
        List<String> packages = listPackages(clazz, fileList);
        // 4. 获取需要的类
        List<String> collect = packages.stream().filter(fullPath -> {
            Annotation res = null;
            try {
                Class c = Class.forName(fullPath);
                res = c.getAnnotation(RequestMapping.class);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return res != null;
        }).collect(Collectors.toList());

        // 解析注解
        Map<String,Bean> mapBeans = beans; // 存放目标类
        for (int i = 0; i < collect.size(); i++) {
            String fullPath = collect.get(i);
            try {
                Class c = Class.forName(fullPath);
                RequestMapping res = (RequestMapping) c.getAnnotation(RequestMapping.class);
                String value = res.value(); // 注解中的 value 值
                // 每遍历一个 类 就创建一个 Bean 对象
                Bean bean = new Bean();
                bean.setClazz(c);
                Map<String,Method> mapMethod = new HashMap<>(); // 存放目标方法
                bean.setMethodMap(mapMethod);

                Method[] methods = c.getMethods();
                for (int j = 0; j < methods.length; j++) {
                    // 方法如果有注解标记 则 保存
                    RequestMapping annotation = methods[j].getAnnotation(RequestMapping.class);
                    if(annotation!=null){
                        String methodValue = annotation.value();
                        mapMethod.put(methodValue,methods[j]);
                    }
                }
                mapBeans.put(value,bean);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    private List<String> listPackages(Class clazz, List<File> fileList) {
        List<String> packages = new ArrayList<>();
        String workUri = clazz.getClassLoader().getResource("").getPath();
        for (int i = 0; i < fileList.size(); i++) {
            String absolutePath = "/" + fileList.get(i).getAbsolutePath().replace("\\", "/");
            String fullPath = absolutePath.replace(workUri, "").replace("/", ".").replace(".class", "");
            packages.add(fullPath);
        }
        return packages;
    }

    private void listFiles(String filePath, List<File> fileList) {
        File file = new File(filePath);
        File[] files = file.listFiles();

        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            if (f.isFile()) {
                fileList.add(f);
            } else {
                listFiles(f.getAbsolutePath(), fileList);
            }
        }

    }


    private String getParentLocation(Class clazz) {
        // 获取 工作 路径
        String workUri = clazz.getClassLoader().getResource("").getPath();
        System.out.println("工作路径：" + workUri);
        // 获取 基本 包路径
        String basePackage = clazz.getPackage().getName();
        // 获取 父 路径
        String parent = workUri + basePackage.replace(".", "/") + "/";
        return parent;
    }

    public Map<String, Bean> getBeans() {
        return beans;
    }

    public Bean getBean(String key) {
        return beans.get(key);
    }
}
